﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using KLadderProposal.Algorithms;
using KLadderProposal.Documents;
using KLadderProposal.Interfaces;
using KLadderProposal.Interfaces.BasicStructures;
using KLadderProposal.Structures;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;

namespace KLadderProposal
{
    /// <summary>
    ///     Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        #region Fields (7)

        private readonly string _folderPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
        private IGraph _graph;
        private IGraphDocument _graphDocument;
        private readonly Random _random1 = new Random();
        private readonly Random _random2 = new Random();
        private readonly Random _random3 = new Random();
        private readonly object _syncObject = new object();

        #endregion Fields

        #region Constructors (1)

        public MainWindow()
        {
            InitializeComponent();

            _graphDocument = new GraphDocument();
        }

        #endregion Constructors

        #region Methods (22)

        // Private Methods (22) 

        private void AfterRun(Stopwatch stopwatch)
        {
            int numberOfNodesWithoutClusterNumber =
                _graph.Nodes.Where(node => node.ClusterNumber == 0).ToArray().Length;

            _numberOfClustersTextBlock.Text =
                _graph.Nodes.Where(node => node.ClusterNumber > 0).
                       Select(node => node.ClusterNumber).Distinct().ToArray().Length.ToString();

            int numberOfNodesWithoutNeigbors =
                _graph.Nodes.Where(node => node.Neighbors.Count == 0).ToArray().Length;

            var ii = from graphNode in _graph.Nodes
                     where graphNode.ClusterNumber > 0
                     group graphNode by graphNode.ClusterNumber
                         into g
                         select new { ClusterNumber = g.Key, Size = g.ToArray().Length };

            _clustersSizesListBox.Items.Clear();
            foreach (var cluster in ii.OrderByDescending(i => i.Size))
                _clustersSizesListBox.Items.Add(cluster.Size);

            _elapsedTimeTextBlock.Text = new DateTime(stopwatch.Elapsed.Ticks).ToString("HH:mm:ss.fff");

            _graph.SaveTo(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "KLadderResults.paj"));
        }

        private void AfterRunJaccard(Stopwatch stopwatch)
        {
            _numberOfClustersTextBlock.Text =
                _graph.Nodes.Where(node => !(node.ClusterNumbers.Count == 0 && node.ClusterNumbers[0] == 0)).
                       SelectMany(node => node.ClusterNumbers).Distinct().ToArray().Length.ToString();

            var ii = from graphNode in _graph.Nodes
                     from clusterNumber in graphNode.ClusterNumbers
                     where !(graphNode.ClusterNumbers.Count == 0) && !(graphNode.ClusterNumbers[0] == 0)
                     group clusterNumber by clusterNumber
                         into g
                         select new { ClusterNumber = g.Key, Size = g.ToArray().Length };

            _clustersSizesListBox.Items.Clear();
            foreach (var cluster in ii.OrderByDescending(i => i.Size))
                _clustersSizesListBox.Items.Add(cluster.Size);

            _elapsedTimeTextBlock.Text = new DateTime(stopwatch.Elapsed.Ticks).ToString("HH:mm:ss.fff");

            foreach (var node in _graph.Nodes)
            {
                node.ClusterNumber = node.ClusterNumbers[0];
            }

            _graph.SaveTo(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "KLadderResults.paj"));
        }

        private bool AreInTheSameCluster(List<List<string>> clusters, string i, string j)
        {
            foreach (var cluster in clusters)
            {
                if (cluster.Any(protein => protein.CompareTo(i) == 0) &&
                    cluster.Any(protein => protein.CompareTo(j) == 0))
                    return true;
            }

            return false;
        }

        private void BrowseButtonClick(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new OpenFileDialog
                                     {
                                         InitialDirectory = Path.Combine(_folderPath, "Network examples"),
                                         FileName = "Document",
                                         DefaultExt = ".txt",
                                         Filter = "Text documents (.txt)|*.txt"
                                     };


            bool? result = openFileDialog.ShowDialog();
            if (result.Value)
            {
                Title = openFileDialog.SafeFileName;
                _filePathTextBox.Text = openFileDialog.FileName;
            }
        }

        private void CreateGraphButtonClick(object sender, RoutedEventArgs e)
        {
            CreateNetwork(out _graph);
        }

        private bool CreateNetwork(out IGraph graph)
        {
            graph = null;
            if (_createSyntheticNetworkRadioButton.IsChecked.Value)
            {
                if (string.IsNullOrWhiteSpace(_syntheticNetworkClustersCountTextBox.Text) ||
                    string.IsNullOrWhiteSpace(_syntheticNetworkSizeTextBox.Text))
                {
                    MessageBox.Show("Please, set size of the network and number of desired clusters.");
                    return false;
                }
                CreateSyntheticNetwork(out graph);
            }
            else
            {
                if (string.IsNullOrWhiteSpace(_filePathTextBox.Text))
                {
                    MessageBox.Show("Please, set file path to the network definition.");
                    return false;
                }

                LoadGraphFromFile(out graph);
            }

            return true;
        }

        private void CreateProteinsReportForJaccardAlgorithm(bool withCommonVertexSearch)
        {
            string currentDirectotyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            string reportfilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
                                                 "JaccardProteins" + (withCommonVertexSearch ? "Advanced" : "Light") +
                                                 ".csv");

            File.WriteAllText(reportfilePath, string.Empty);
            File.WriteAllText(Path.Combine(currentDirectotyPath, "reportErrors.txt"), string.Empty);

            var csvReport = new StringBuilder();
            bool isParallel = false;//_parallelRadioButton.IsChecked.HasValue ? _parallelRadioButton.IsChecked.Value : false;
            int thresholdInterval = 10;

            var graphs = new List<IGraph>();
            for (int i = 0; i <= 30; i++)
            {
                IGraph graph1;
                CreateNetwork(out graph1);
                graphs.Add(graph1);
            }

            Parallel.For(24, 31, index =>
                {
                    int threshold = thresholdInterval * index;
                    try
                    {
                        IGraph graph = graphs[index - 1];

                        IAlgorithm jaccardAlgorithm = new JaccardBasedAlgorithm();
                        ((JaccardBasedAlgorithm)jaccardAlgorithm).Threshold = threshold;
                        ((JaccardBasedAlgorithm)jaccardAlgorithm).IsParallel = isParallel;
                        ((JaccardBasedAlgorithm)jaccardAlgorithm).RunCommonVertexSearchStep =
                            withCommonVertexSearch;
                        jaccardAlgorithm.Run(graph); //_graph

                        var clusters = from graphNode in graph.Nodes
                                       from clusterNumber in graphNode.ClusterNumbers
                                       where !(graphNode.ClusterNumbers.Count == 0) &&
                                           !(graphNode.ClusterNumbers[0] == 0)
                                       group clusterNumber by clusterNumber
                                           into g
                                           select new { ClusterNumber = g.Key, Size = g.ToArray().Length };

                        lock (_syncObject)
                        {
                            if (clusters.Any())
                            {
                                int clusterNumberWithMaxMembers =
                                    clusters.OrderByDescending(i => i.Size).First().ClusterNumber;
                                File.AppendAllLines(reportfilePath, new[]
                                        {
                                            string.Format("{0},{1}", threshold,
                                                        graph.Nodes.Where(node => 
                                                            node.ClusterNumbers.Contains(clusterNumberWithMaxMembers)).
                                                                OrderBy(node => node.Label).Select(node => node.Label).
                                                                Aggregate((first, second) => first + "," + second))
                                        });
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        lock (_syncObject)
                        {
                            File.AppendAllText(
                                Path.Combine(currentDirectotyPath, "reportErrors.txt"),
                                "\r\nThreshold = " + threshold + "\r\n" + exception.Message +
                                (exception.StackTrace != null ? exception.StackTrace : string.Empty));
                        }
                    }
                });
        }

        private void CreateReportButtonClick(object sender, RoutedEventArgs e)
        {
            //CreateReportForJaccardAlgorithm(!_doNotRunCommonVertexSearchStepCheckBox.IsChecked.Value);
            //CreateProteinsReportForJaccardAlgorithm(!_doNotRunCommonVertexSearchStepCheckBox.IsChecked.Value);
            CreateJaccardReports(!_doNotRunCommonVertexSearchForReportStepCheckBox.IsChecked.Value);
        }

        private void CreateReportForJaccardAlgorithm(bool withCommonVertexSearch)
        {
            string currentDirectotyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            string reportfilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
                                                 "Jaccard" + (withCommonVertexSearch ? "Advanced" : "Light") + ".csv");

            File.WriteAllText(reportfilePath, string.Empty);
            File.WriteAllText(Path.Combine(currentDirectotyPath, "reportErrors.txt"), string.Empty);

            var csvReport = new StringBuilder();
            csvReport.AppendLine(
                "Threshold,cluster1,cluster2,cluster3,cluster4,cluster5,cluster6,cluster7,cluster8,cluster9,cluster10");
            File.AppendAllLines(reportfilePath,
                                new[]
                                    {
                                        "Threshold,cluster1,cluster2,cluster3,cluster4,cluster5,cluster6,cluster7,cluster8,cluster9,cluster10"
                                    });

            bool isParallel = false;//_parallelRadioButton.IsChecked.HasValue ? _parallelRadioButton.IsChecked.Value : false;
            int thresholdInterval = 10;

            var graphs = new List<IGraph>();
            for (int i = 0; i <= 30; i++)
            {
                IGraph graph1;
                CreateNetwork(out graph1);
                graphs.Add(graph1);
            }

            try
            {
                Parallel.For(1, 31, index =>
                    //for (int threshold = 30 * thresholdInterval; threshold >= thresholdInterval ; threshold -= thresholdInterval)
                    {
                        int threshold = thresholdInterval * index;
                        lock (_syncObject)
                        {
                            File.AppendAllText(
                                Path.Combine(currentDirectotyPath, "thresholds.txt"),
                                threshold + System.Environment.NewLine);
                        }
                        try
                        {
                            IGraph graph = graphs[index - 1];

                            IAlgorithm jaccardAlgorithm = new JaccardBasedAlgorithm();
                            ((JaccardBasedAlgorithm)jaccardAlgorithm).Threshold = threshold;
                            ((JaccardBasedAlgorithm)jaccardAlgorithm).IsParallel = isParallel;
                            ((JaccardBasedAlgorithm)jaccardAlgorithm).RunCommonVertexSearchStep =
                                withCommonVertexSearch;
                            jaccardAlgorithm.Run(graph); //_graph

                            var clusters = from graphNode in graph.Nodes
                                           from clusterNumber in graphNode.ClusterNumbers
                                           where !(graphNode.ClusterNumbers.Count == 0) &&
                                               !(graphNode.ClusterNumbers[0] == 0)
                                           group clusterNumber by clusterNumber
                                               into g
                                               select new
                                                       {
                                                           ClusterNumber = g.Key,
                                                           Size = g.ToArray().Length
                                                       };

                            //_elapsedTimeTextBlock.Text = new DateTime(stopwatch.Elapsed.Ticks).ToString("HH:mm:ss.fff");

                            lock (_syncObject)
                            {
                                if (clusters.Any())
                                {
                                    File.AppendAllLines(reportfilePath, new[]
                                        {
                                            string.Format("{0},{1}", threshold, //csvReport.AppendLine(string.Format("{0},{1}", threshold,
                                                clusters.OrderByDescending(i => i.Size).
                                                Select(cluster=> cluster.Size.ToString()).Take(10).
                                                        Aggregate((first, second) => first + "," + second))
                                        });
                                }
                                else
                                {
                                    File.AppendAllLines(reportfilePath,
                                                        new[]
                                                            {
                                                                string.Format("{0},{1}", threshold,
                                                                                "0,0,0,0,0,0,0,0,0,0")
                                                            });
                                    //csvReport.AppendLine(string.Format("{0},{1}", threshold, "0,0,0,0,0,0,0,0,0,0"));
                                }
                            }
                        }
                        catch (Exception exception)
                        {
                            lock (_syncObject)
                            {
                                File.AppendAllText(
                                    Path.Combine(currentDirectotyPath, "reportErrors.txt"),
                                    "\r\nThreshold = " + threshold + "\r\n" + exception.Message +
                                    (exception.StackTrace != null
                                            ? exception.StackTrace
                                            : string.Empty));
                            }
                        }
                    });
            }
            finally
            {
                //File.AppendAllText(reportfilePath, csvReport.ToString());
            }
        }

        private void CreateJaccardReports(bool withCommonVertexSearch)
        {
            if (!ValidateInput())
                return;

            string currentDirectotyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            string reportfilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
                                                 "Jaccard_NumberOfClusters" + (withCommonVertexSearch ? "_Advanced" : "_Light") + ".csv");
            string proteinsReportfilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
                                                "Jaccard_Proteins" + (withCommonVertexSearch ? "_Advanced" : "_Light") + ".csv");

            InitializeFilesUsedForJaccardReport(currentDirectotyPath, reportfilePath, proteinsReportfilePath);

            bool isParallel = false;//_parallelRadioButton.IsChecked.HasValue ? _parallelRadioButton.IsChecked.Value : false;
            int thresholdInterval = int.Parse(_intervalThresholdTextBox.Text);//Validate before use
            int fromThreshold = int.Parse(_fromThresholdTextBox.Text);
            int toThreshold = int.Parse(_toThresholdTextBox.Text);

            var graphs = CreateGraphsForEachThresholdForJaccardReport(thresholdInterval, fromThreshold, toThreshold);

            Parallel.For(0, (toThreshold - fromThreshold) / thresholdInterval + 1, index =>
            {
                int threshold = fromThreshold + thresholdInterval * index;
                lock (_syncObject)
                {
                    File.AppendAllText(Path.Combine(currentDirectotyPath, "thresholdsSoFar.txt"),
                        threshold + System.Environment.NewLine);
                }
                try
                {
                    IGraph graph = graphs[index];

                    IAlgorithm jaccardAlgorithm = new JaccardBasedAlgorithm();
                    ((JaccardBasedAlgorithm)jaccardAlgorithm).Threshold = threshold;
                    ((JaccardBasedAlgorithm)jaccardAlgorithm).IsParallel = isParallel;
                    ((JaccardBasedAlgorithm)jaccardAlgorithm).RunCommonVertexSearchStep = withCommonVertexSearch;
                    jaccardAlgorithm.Run(graph);

                    var clusters = from graphNode in graph.Nodes
                                   from clusterNumber in graphNode.ClusterNumbers
                                   where !(graphNode.ClusterNumbers.Count == 0) &&
                                       !(graphNode.ClusterNumbers[0] == 0)
                                   group clusterNumber by clusterNumber
                                       into g
                                       select new
                                       {
                                           ClusterNumber = g.Key,
                                           Size = g.ToArray().Length
                                       };

                    lock (_syncObject)
                    {
                        if (clusters.Any())
                        {
                            //update report1 with cluster sizes for specific threshold
                            File.AppendAllLines(reportfilePath, new[]
                                        {
                                            string.Format("{0},{1}", threshold, 
                                            clusters.OrderByDescending(i => i.Size).
                                                Select(cluster=> cluster.Size.ToString()).Take(10).
                                                        Aggregate((first, second) => first + "," + second))
                                        });

                            //aggregate lines per threshold for report2 
                            List<string> proteinReportLines = new List<string>();
                            foreach (var clusterDetails in clusters.
                                Where(details => details.Size > 2).OrderBy(details => details.Size))
                            {
                                string proteinReportLine = threshold.ToString() + ",";
                                proteinReportLine += graph.Nodes.
                                    Where(node => node.ClusterNumbers.Contains(clusterDetails.ClusterNumber)).
                                    Select(node => node.Label).OrderBy(label => label).Aggregate((first, second) => first + "," + second);
                                proteinReportLines.Add(proteinReportLine);
                            }

                            //update report2 with protein names per each cluster per threshold
                            File.AppendAllLines(proteinsReportfilePath, proteinReportLines.ToArray());
                        }
                        else
                        {
                            File.AppendAllLines(reportfilePath, new[] { 
                                string.Format("{0},{1}", threshold, "0,0,0,0,0,0,0,0,0,0")});
                        }
                    }
                }
                catch (Exception exception)
                {
                    lock (_syncObject)
                    {
                        File.AppendAllText(Path.Combine(currentDirectotyPath, "reportErrors.txt"),
                            "\r\nThreshold = " + threshold + "\r\n" + exception.Message +
                            (exception.StackTrace != null ? exception.StackTrace : string.Empty));
                    }
                }
            });
        }

        private bool ValidateInput()
        {
            int validator;

            if (!int.TryParse(_fromThresholdTextBox.Text, out validator))
            {
                MessageBox.Show("'From threshold' value is not valid.");
                return false;
            }

            if (!int.TryParse(_toThresholdTextBox.Text, out validator))
            {
                MessageBox.Show("'To threshold' value is not valid.");
                return false;
            }

            if (!int.TryParse(_intervalThresholdTextBox.Text, out validator))
            {
                MessageBox.Show("'Threshold interval' value is not valid.");
                return false;
            }

            return true;
        }

        private List<IGraph> CreateGraphsForEachThresholdForJaccardReport(int thresholdInterval, int fromThreshold, int toThreshold)
        {
            var graphs = new List<IGraph>();
            for (int i = 0; i <= (toThreshold - fromThreshold) / thresholdInterval + 1; i++)
            {
                IGraph graph1;
                CreateNetwork(out graph1);
                graphs.Add(graph1);
            }
            return graphs;
        }

        private static void InitializeFilesUsedForJaccardReport(string currentDirectotyPath, string reportfilePath, string proteinsReportfilePath)
        {
            File.WriteAllText(reportfilePath, string.Empty);
            File.WriteAllText(proteinsReportfilePath, string.Empty);

            File.WriteAllText(Path.Combine(currentDirectotyPath, "reportErrors.txt"), DateTime.Now.ToString() +
                System.Environment.NewLine);
            File.WriteAllText(Path.Combine(currentDirectotyPath, "thresholdsSoFar.txt"), string.Empty);

            File.WriteAllLines(reportfilePath,
                                new[]
                                    {
                                        "Threshold,cluster1,cluster2,cluster3,cluster4,cluster5,cluster6,cluster7,cluster8,cluster9,cluster10"
                                    });
            File.WriteAllLines(proteinsReportfilePath, new[] { "Threshold" });
        }

        private void CreateSyntheticNetwork(out IGraph graph)
        {
            int networkSize = int.Parse(_syntheticNetworkSizeTextBox.Text);
            int numberOfClusters = int.Parse(_syntheticNetworkClustersCountTextBox.Text);

            CreateSyntheticNetwork(out graph, networkSize, numberOfClusters);
        }

        private void CreateSyntheticNetwork(out IGraph graph, int networkSize, int numberOfClusters)
        {
            var clusters = new List<List<string>>(numberOfClusters);
            graph = new Graph(_graphDocument);
            for (int i = 0; i < numberOfClusters; i++)
                clusters.Add(new List<string>());

            for (int i = 1; i <= networkSize; i++)
            {
                int clusterNumber = _random1.Next(0, numberOfClusters);
                clusters[clusterNumber].Add(i.ToString());
            }

            var interactions = new List<KeyValuePair<string, string>>();

            for (int i = 1; i <= networkSize; i++)
            {
                for (int j = 1; j <= networkSize; j++)
                {
                    if (i == j)
                        continue;

                    if (AreInTheSameCluster(clusters, i.ToString(), j.ToString()))
                    {
                        int probability09 = _random2.Next(1, 11);
                        bool hasInteraction = (probability09 != 10);
                        if (hasInteraction)
                            interactions.Add(new KeyValuePair<string, string>(i.ToString(), j.ToString()));
                    }
                    else
                    {
                        int probability001 = _random3.Next(1, 101);
                        bool hasInteraction = (probability001 == 1);
                        if (hasInteraction)
                            interactions.Add(new KeyValuePair<string, string>(i.ToString(), j.ToString()));
                    }
                }
            }

            for (int i = 1; i < interactions.Count; i++)
            {
                graph.AddUndirectedEdge(interactions[i].Key, interactions[i].Value);
            }
        }

        private void LoadGraphFromFile(out IGraph graph)
        {
            graph = new Graph(_graphDocument);
            graph.LoadFrom(_filePathTextBox.Text);
        }

        private void OpenResultsInPajekButtonClick(object sender, RoutedEventArgs e)
        {
            if (Application.Current.Properties["PajekExePath"] == null)
            {
                MessageBox.Show("You will be promted to set pajek.exe path on your computer.");

                var openFileDialog = new OpenFileDialog
                                         {
                                             Title = "Please, choose Pajek exe file.",
                                             FileName = "Document",
                                             DefaultExt = ".exe",
                                             Filter = "Application (.exe)|*.exe",
                                             InitialDirectory = @"C:\Program Files (x86)\Pajek"
                                         };

                bool? result = openFileDialog.ShowDialog();
                if (result.Value)
                {
                    Application.Current.Properties["PajekExePath"] = openFileDialog.FileName;
                }
                else
                    return;
            }

            string currentDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            string logContent = File.ReadAllText(Path.Combine(_folderPath, @"Pajek log files\pajek.log"));
            string pajekLogFilePath =
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
                             "kladderPajek.log");
            logContent = string.Format(logContent, currentDirectory);
            File.WriteAllText(pajekLogFilePath, logContent);

            var process = new Process();
            var startInfo = new ProcessStartInfo
                                {
                                    WindowStyle = ProcessWindowStyle.Hidden,
                                    FileName = "\"" + Application.Current.Properties["PajekExePath"] + "\"",
                                    Arguments = "\"" + pajekLogFilePath + "\""
                                };
            process.StartInfo = startInfo;
            process.Start();
        }

        private void ParseResultsToCsvClick(object sender, RoutedEventArgs e)
        {
            StructureAlgorithm.ParseFile();
        }

        private void ResetGraph()
        {
            foreach (GraphNode node in _graph.Nodes)
            {
                node.ClusterNumber = 0;
                node.IsMarkedAsDeleted = false;
                node.ThreeCliqueNumber = 0;
                node.TempClusterNumber = 0;
                node.ClusterNumbers = new List<int>();
            }
        }

        private void RunJaccardAlgorithmButtonClick(object sender, RoutedEventArgs e)
        {
            int threshold;
            if (!int.TryParse(_thresholdTextBox.Text, out threshold))
            {
                MessageBox.Show("Threshold is not valid.");
                return;
            }

            //_graphDocument = new GraphDocumentForOverlapingClusters();
            if (_graph == null)
            {
                if (CreateNetwork(out _graph) == false)
                    return;
            }
            else
                ResetGraph();

            IAlgorithm jaccardAlgorithm = new JaccardBasedAlgorithm();
            ((JaccardBasedAlgorithm)jaccardAlgorithm).Threshold = int.Parse(_thresholdTextBox.Text);
            ((JaccardBasedAlgorithm)jaccardAlgorithm).IsParallel = false;//_parallelRadioButton.IsChecked.HasValue ? _parallelRadioButton.IsChecked.Value : false;
            ((JaccardBasedAlgorithm)jaccardAlgorithm).RunCommonVertexSearchStep =
                !_doNotRunCommonVertexSearchStepCheckBox.IsChecked.Value;

            var stopwatch = new Stopwatch();
            stopwatch.Start();
            jaccardAlgorithm.Run(_graph);
            stopwatch.Stop();

            AfterRunJaccard(stopwatch);
        }

        private void RunMultiLevelButtonClick(object sender, RoutedEventArgs e)
        {
            if (_graph == null)
            {
                if (CreateNetwork(out _graph) == false)
                    return;
            }
            else
                ResetGraph();

            IAlgorithm jaccardAlgorithm = new MultiLevelAlgorithm();

            var stopwatch = new Stopwatch();
            stopwatch.Start();
            jaccardAlgorithm.Run(_graph);
            stopwatch.Stop();

            AfterRun(stopwatch);
        }

        private void RunStructureCliqueAlgorithm(IGraph graph)
        {
            StructureAlgorithm algorithm = new StructureAlgorithm();
            algorithm.Treshold = Convert.ToDouble(StructureThresholdTextBox.Text);
            algorithm.CliqueSize = Convert.ToInt32(CliqueSizeTextBox.Text);
            algorithm.Text = Title;

            var stopwatch = new Stopwatch();
            stopwatch.Start();
            algorithm.Run(_graph);
            stopwatch.Stop();

            _numberOfClustersTextBlock.Text =
                _graph.Nodes.Where(node => node.ClusterNumber > 0).
                       Select(node => node.ClusterNumber).Distinct().ToArray().Length.ToString();

            var ii = from graphNode in _graph.Nodes
                     where graphNode.ClusterNumber > 0
                     group graphNode by graphNode.ClusterNumber
                         into g
                         select new { ClusterNumber = g.Key, Size = g.ToArray().Length };

            _clustersSizesListBox.Items.Clear();
            foreach (var cluster in ii.OrderByDescending(i => i.Size))
                _clustersSizesListBox.Items.Add(cluster.Size);

            _elapsedTimeTextBlock.Text = new DateTime(stopwatch.Elapsed.Ticks).ToString("HH:mm:ss.fff");

            _graph.SaveTo(Path.Combine(_folderPath, "KLadderResults.paj"));
            SaveResults(Path.Combine(_folderPath, "StructureAlgorithmResults.csv"));
        }

        private void RunStructureCliqueAlgorithmButtonClick(object sender, RoutedEventArgs e)
        {
            if (_graph == null)
            {
                if (CreateNetwork(out _graph) == false)
                    return;
            }
            else
                ResetGraph();

            RunStructureCliqueAlgorithm(_graph);
        }

        private void SaveResults(string filePath)
        {
            try
            {
                var list = new List<float>();
                int value;
                int total = _graph.Nodes.Count();
                float div;
                foreach (object item in _clustersSizesListBox.Items)
                {
                    int.TryParse(item.ToString(), out value);
                    //div = (float)value / total;
                    list.Add(value);
                }
                string s = string.Join(",", list.ToArray());
                string s1 = string.Format("Graph ,{0},clique size,{1},Threshold,{2},Time, {3},{4}{5}{4}",
                                          Title,
                                          CliqueSizeTextBox.Text,
                                          StructureThresholdTextBox.Text,
                                          _elapsedTimeTextBlock.Text,
                                          Environment.NewLine, s);
                File.AppendAllText(filePath, string.Format(s1));
            }
            catch
            {
            }
        }

        private void WindowActivated(object sender, EventArgs e)
        {
            //string folderPath = Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), @"..\..\Network examples"));
            //_filePathTextBox.Text = Path.Combine(folderPath, "VerySmallNetwork.txt");
        }

        #endregion Methods

        private void RunStructureCliqueAlgorithmWithOutDeleteButtonClick(object sender, RoutedEventArgs e)
        {
            if (_graph == null)
            {
                if (CreateNetwork(out _graph) == false)
                    return;
            }
            else
                ResetGraph();

            StructureAlgorithm1 algorithm = new StructureAlgorithm1();
            algorithm.Treshold = Convert.ToDouble(StructureThresholdTextBox.Text);
            algorithm.CliqueSize = Convert.ToInt32(CliqueSizeTextBox.Text);
            algorithm.Text = Title;

            var stopwatch = new Stopwatch();
            stopwatch.Start();
            algorithm.Run(_graph);
            stopwatch.Stop();

            _numberOfClustersTextBlock.Text =
                _graph.Nodes.Where(node => node.ClusterNumber > 0).
                       Select(node => node.ClusterNumber).Distinct().ToArray().Length.ToString();

            var ii = from graphNode in _graph.Nodes
                     where graphNode.ClusterNumber > 0
                     group graphNode by graphNode.ClusterNumber
                         into g
                         select new { ClusterNumber = g.Key, Size = g.ToArray().Length };

            _clustersSizesListBox.Items.Clear();
            foreach (var cluster in ii.OrderByDescending(i => i.Size))
                _clustersSizesListBox.Items.Add(cluster.Size);

            _elapsedTimeTextBlock.Text = new DateTime(stopwatch.Elapsed.Ticks).ToString("HH:mm:ss.fff");

            _graph.SaveTo(Path.Combine(_folderPath, "KLadderResults.paj"));
            SaveResults(Path.Combine(_folderPath, "StructureAlgorithmResultsWithoutDelete.csv"));
        }

        private void SaveNetworkFileButtonClick(object sender, RoutedEventArgs e)
        {
            string sourceFile = Path.Combine(_folderPath, "KLadderResults.paj");
            string destFile;

            FolderBrowserDialog dialog = new FolderBrowserDialog();
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                destFile = Path.Combine(dialog.SelectedPath, string.Format("KLadderResults{0:hh-dd}.paj", DateTime.Now));
                File.Copy(sourceFile, destFile, true);

                using (StreamWriter sw =
                    new StreamWriter(Path.Combine(dialog.SelectedPath, "Network.txt"), false))
                {
                    foreach (GraphNode node in _graph.Nodes)
                    {
                        foreach (KeyValuePair<string, GraphNode> neighbor in node.Neighbors)
                        {
                            sw.WriteLine("{0}\t{1}",
                                         node.Label,
                                         neighbor.Key);
                        }
                    }
                }
            }
        }
    }
}